package com.ruoyi.flowable.cmd;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.flowable.exception.FlowableException;
import com.ruoyi.flowable.exception.FlowableModelKeyExistsException;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.ProcessEngineConfiguration;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.repository.Model;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayInputStream;
import java.io.InputStreamReader;
import java.io.Serializable;

/**
 * @program: RuoYi-Vue
 * @description: 保存模型并生成图片
 * @author: jhw
 * @create: 2021-04-06 14:33
 **/
public class SaveModelEditCmd  implements Command<Void>, Serializable {
    private static final long serialVersionUID = 1L;
    private String modelId;
    private String tenantId;
    private String editor;
    private String key;
    private String name;
    private String category;
    private String description;

    public SaveModelEditCmd(String modelId, String editor) {
        this.modelId = modelId;
        this.editor = editor;
    }
    public SaveModelEditCmd(String modelId, String key, String name, String category, String description) {
        this.modelId = modelId;
        this.key = key;
        this.name = name;
        this.category = category;
        this.description = description;
    }
    @Override
    public Void execute(CommandContext commandContext) {
        ProcessEngineConfiguration processEngineConfiguration =
                CommandContextUtil.getProcessEngineConfiguration(commandContext);
        RepositoryService service = processEngineConfiguration.getRepositoryService();

        if(modelId==null&&editor==null){
            throw  new FlowableException("flowable.model.saveError",new Object[]{"modelId and xml is null"});
        }

        BpmnModel bpmnModel=null;
        byte[] xml = null;
        try{
            //新增
            if(StringUtils.isNotEmpty(editor)){
                xml = editor.getBytes();
                XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
                InputStreamReader isr = new InputStreamReader(new ByteArrayInputStream(xml),"UTF-8");
                XMLStreamReader xsr = xmlInputFactory.createXMLStreamReader(isr);
                bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xsr);
                key = bpmnModel.getMainProcess().getId();
                name = bpmnModel.getMainProcess().getName();
                category = bpmnModel.getTargetNamespace();
                description = bpmnModel.getMainProcess().getDocumentation();
            }else{
                //修改
                byte[] oldXml = service.getModelEditorSource(modelId);
                if (oldXml != null) {
                    XMLInputFactory xif = XMLInputFactory.newInstance();
                    InputStreamReader xmlIn = new InputStreamReader(new ByteArrayInputStream(oldXml), "UTF-8");
                    XMLStreamReader xtr = xif.createXMLStreamReader(xmlIn);
                    BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
                    bpmnModel = bpmnXMLConverter.convertToBpmnModel(xtr);
                    bpmnModel.setTargetNamespace(category);
                    bpmnModel.getMainProcess().setId(key);
                    bpmnModel.getMainProcess().setName(name);
                    bpmnModel.getMainProcess().setDocumentation(description);
                    xml = bpmnXMLConverter.convertToXML(bpmnModel, "UTF-8");
                }
            }
            Model model = null;
            if(StringUtils.isNotEmpty(modelId)){
                model = service.createModelQuery().modelId(modelId).singleResult();
            }else {
                model = service.newModel();
            }

            if (!key.equals(model.getKey())){
                long count = service.createModelQuery().modelKey(key).count();
                if (count>0){
                    throw new FlowableModelKeyExistsException(key);
                }
            }
            model.setKey(key);
            model.setName(name);
            model.setCategory(category);
            model.setMetaInfo(getMetaInfo(name,description));
            service.saveModel(model);

            if(xml!=null){
                service.addModelEditorSource(modelId,xml);
            }
        }catch (Exception e){
            throw  new FlowableException("flowable.model.saveError",new Object[]{e.getMessage()});
        }


        return null;
    }

    protected String getMetaInfo(String name, String description) {
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode metaInfo = objectMapper.createObjectNode();
        metaInfo.put("name", name);
        metaInfo.put("description", description);
        return metaInfo.toString();
    }
}
